package com.shenyong.ladmin.logConfig;

import com.shenyong.controller.BaseController;
import com.shenyong.controller.LoginController;
import com.shenyong.entity.LoginUsers;
import com.shenyong.entity.Users;
import com.shenyong.ladmin.mapper.SysOperationLogMapper;
import com.shenyong.service.UserService;
import com.shenyong.util.JwtToken;
import com.shenyong.util.JwtUtil;
import com.shenyong.util.StringUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import com.alibaba.fastjson.JSONObject;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.lang.reflect.Method;
import java.util.Date;


/**
 * 系统日志：切面处理类
 */
@Aspect
@Component
public class SysLogAspects {
    private static final Logger logger = LoggerFactory.getLogger(SysLogAspects.class);
    @Autowired
    private UserService userService;

    @Autowired
    private SysOperationLogMapper sysOperationLogMapper;//这个service主要用来保存日志记录实体到数据库

    @Autowired
    private BaseController baseController;//系统公共controller

    //@Autowired
   // private UserJpaService userJpaService;//这个service主要用来保存和查询用户表


    //定义切点 @Pointcut
    //在注解的位置切入代码
    @Pointcut(value="@annotation(com.shenyong.ladmin.logConfig.Log)")
    public void logPoinCut() {
    }

    /*切面 配置通知，各注解作用
    *@Before:前置通知，在方法执行之前执行
    *@After:后置通知，在方法执行之后执行
    *@AfterRunning:返回通知，在方法返回结果之后执行，用这个注解参数会随方法改变，例新增一个实体，参数是一个id为null的，用这个注解后就会赋上真实的id
    *@AfterThrowing:异常通知，在方法抛出异常之后执行
    *@Around：环绕通知，围绕着方法执行
    * */
    @After("logPoinCut()")
    public void saveSysLog(JoinPoint joinPoint) {
        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();
        //操作简述
        String describe="";
        //操作类型的枚举
        OperationType operationType=OperationType.OTHER;
        Log log = method.getAnnotation(Log.class);
        if (log != null) {
            describe = log.describe()!=null? log.describe():"未知";
            operationType= log.operationType()!=null?log.operationType():OperationType.OTHER;
        }
        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();
        //请求的参数
        Object[] args = joinPoint.getArgs();
        Object[] arguments  = new Object[args.length];
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof ServletRequest || args[i] instanceof ServletResponse || args[i] instanceof MultipartFile) {
                //ServletRequest不能序列化，从入参里排除，否则报异常：java.lang.IllegalStateException: It is illegal to call this method if the current request is not in asynchronous mode (i.e. isAsyncStarted() returns false)
                //ServletResponse不能序列化 从入参里排除，否则报异常：java.lang.IllegalStateException: getOutputStream() has already been called for this response
                continue;
            }
            arguments[i] = args[i];
        }
        //将参数所在的数组转换成json
        String params = "";
        if (arguments != null) {
            try {
                params = JSONObject.toJSONString(arguments);
            } catch (Exception e) {
                params = arguments.toString();
            }
        }
        int userid=0;
        String nickName="";
        try {
            /*用户还未登录*/
            if(operationType==OperationType.LOGON){
                /*获取将要登录的用户的用户名*/
                String userName= StringUtil.safeToString(arguments[0],"");
                /*根据用户名获取昵称*/
                /*nickName=userJpaService.getNickNameByName(userName);*/
                /*根据用户名获取用户id*/
                //userid=userJpaService.getUserIdByName(userName);
                userid=1;
                /*登录时参数包含用户名和密码等关键信息，为安全起见，不记录参数*/
                params="******";
            }else{
                /*获取系统当前登录用户的用户名*/
                String nickName1= baseController.getToken();
                nickName= JwtUtil.getUsername(nickName1);
                LoginUsers user= userService.getName(nickName);
                userid=user.getUser().getUser_id();
            }
        } catch (Exception e) {
            logger.info("获取当前用户出错:{}", e.getMessage());
        }
        //保存日志
        SysOperationLog sysLog = new SysOperationLog();
        sysLog.setOperationDescribe(describe);
        sysLog.setMethod(className + "." + methodName);
        sysLog.setParams(params);
        sysLog.setUserId(new Long((long) userid));
        sysLog.setUserName(nickName);
        sysLog.setOperationType(operationType);
        sysLog.setCreateTime(new Date());
        logger.info("【操作记录】用户:{},在:{},进行了:{}操作,调用方法:{}",sysLog.getUserName(),sysLog.getCreateTime(),sysLog.getOperationDescribe(),sysLog.getMethod());
        sysOperationLogMapper.save(sysLog);
    }
}
